home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume2 / libraris / gimme.6 < prev    next >
Text File  |  1988-12-02  |  58KB  |  2,453 lines

  1. Path: xanth!mcnc!gatech!bloom-beacon!mit-eddie!ll-xn!adelie!infinet!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v02i079:  gimme.lib - misc library routines, Part06/07
  5. Message-ID: <10417@swan.ulowell.edu>
  6. Date: 2 Dec 88 01:03:44 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 2442
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: oscvax!jan@uunet.UU.NET (Jan Sven Trabandt)
  12. Posting-number: Volume 2, Issue 79
  13. Archive-name: libraries/gimme.6
  14.  
  15. #    This is a shell archive.
  16. #    Remove everything above and including the cut line.
  17. #    Then run the rest of the file through sh.
  18. #----cut here-----cut here-----cut here-----cut here----#
  19. #!/bin/sh
  20. # shar:    Shell Archiver
  21. #    Run the following text with /bin/sh to create:
  22. #    picture.c
  23. #    postext.c
  24. #    requester.c
  25. #    screen.c
  26. #    scrollbar.c
  27. #    sound.c
  28. #    stdstuff.c
  29. #    subtask.c
  30. #    subtinit.c
  31. #    timer.c
  32. #    timerstuff.c
  33. #    window.c
  34. # This archive created: Thu Dec  1 19:52:33 1988
  35. cat << \SHAR_EOF > picture.c
  36. /*
  37.  *  FILE: picture.c
  38.  *  Support routines for reading IFF/ILBM files.
  39.  *
  40.  *  Public Domain, but keep our names in it as the original authors.
  41.  *  08-Dec-87    Rico Mariani        original code (modified by JST)
  42.  *  31-Aug-88    Jan Sven Trabandt   first release version
  43.  */
  44.  
  45.  
  46. #define I_AM_PICTURE
  47. #include "gimmelib/gimmefuncs.h"
  48. #include "gimmelib/picture.h"
  49. #include "gimmelib/postext.h"
  50. #include "gimmelib/minterm.h"
  51. #include <stdio.h>
  52.  
  53.  
  54. #define GET(iffile)         getc( iffile )
  55.  
  56. #define getId            getLong
  57. #define getLen            getLong
  58. #define getByte         GET
  59. #define skip(len, file)     fseek(file, (long)(len), 1)
  60.  
  61. #define getBMH(bmh, file)   fread(bmh, sizeof(BitMapHeader), 1, file)
  62.  
  63. /* requires an existent variable 'char *errmsg' and a label 'failure_return' */
  64. #define fail_and_return(msg)    {errmsg = msg; goto failure_return;}
  65.  
  66. /* forward declarations */
  67. static LONG getLong();
  68. static WORD getWord();
  69. static ULONG makeBM();
  70.  
  71. static char noMemMsg[] = "insufficient memory\n";
  72. static char badFileMsg[] = "corrupt or incomplete file\n";
  73.  
  74.  
  75. PICTURE *gimmePicture( filename, myflags )
  76.     UBYTE   *filename;
  77.     ULONG   myflags;
  78. {
  79.     LONG    len, id;
  80.     PICTURE *pic = NULL;
  81.     BYTE    *p;
  82.     void    *mh = NULL;
  83.     FILE    *file = NULL;
  84.     char    *errmsg = " ";
  85.     SHORT   i;
  86.  
  87.     if( !(file = fopen(filename, "r")) ) {
  88.     fail_and_return( "unable to open iff picture file for read\n" );
  89.     }
  90.     if( getId(file) != ID_FORM ) {
  91.     fail_and_return( "not IFF format\n" );
  92.     }
  93.     getLen( file );
  94.     if( getId(file) != ID_ILBM ) {
  95.     fail_and_return( "not ILBM format\n" );
  96.     }
  97.     for( ;; ) {
  98.     getChunk( &id, &len, file );
  99.     if( ferror(file) || feof(file) ) {
  100.         fail_and_return( badFileMsg );
  101.     }
  102.     switch( id ) {
  103.       case ID_BMHD:
  104.         pic = chainAllocMem( &mh, (ULONG)sizeof(PICTURE),
  105.                     MEMF_PUBLIC | MEMF_CLEAR );
  106.         if( !pic ) {
  107.            fail_and_return( noMemMsg );
  108.         }
  109.         getBMH( &pic->bmh, file );
  110.         if( len & 1 ) {
  111.         GET(file);
  112.         }
  113.         break;
  114.       case ID_CMAP:
  115.         if( getLut(pic, len, file) ) {
  116.         fail_and_return( "unable to get color table\n" );
  117.         }
  118.         break;
  119.       case ID_BODY:
  120.         if( !pic ) {
  121.         fail_and_return( "didn't find BMHD chunk\n" );
  122.         return( NULL );
  123.         }
  124.         switch( pic->bmh.masking ) {
  125.           case mskNone:
  126.           case mskLasso:
  127.           case mskHasTranCol:
  128.         break;
  129.           default:
  130.         printf("Error, unsupported masking type\n");
  131.         return( NULL );
  132.         } /* switch */
  133.  
  134.         pic->xsize = pic->bmh.w;
  135.         if( (pic->myflags = makeBM(pic, myflags)) == GBP_ERROR ) {
  136.         return( NULL );
  137.         }
  138.         switch( pic->bmh.compression ) {
  139.           case cmpNone:
  140.         if( getBody(pic->bm, pic->myflags, file) ) {
  141.             fail_and_return( "error in uncompressed body\n" );
  142.         }
  143.         break;
  144.           case cmpByteRun1:
  145.         if( getCmpBody(pic->bm, file) ) {
  146.             fail_and_return( "error in compressed body\n" );
  147.         }
  148.         break;
  149.           default:
  150.         fail_and_return( "unknown compression form\n" );
  151.         return( NULL );
  152.         } /* switch */
  153.         if( ferror(file) ) {
  154.         fail_and_return( badFileMsg );
  155.         }
  156.         pic->memhead = mh;
  157.         fclose( file );
  158.         return( pic );
  159.         break;
  160.       case ID_DEST:
  161.       case ID_SPRT:
  162.       case ID_CAMG:
  163.       case ID_CRNG:
  164.       case ID_CCRT:
  165.       default:        /* unimplemented chunk type */
  166.         skip( EVEN(len), file );
  167.         break;
  168.     } /* switch */
  169.     } /* for */
  170. failure_return: {}
  171.     if( Output() ) {
  172.     Write( Output(), errmsg, (ULONG)strlen(errmsg) );
  173.     }
  174.     if( mh ) {
  175.     chainFreeMem( mh );
  176.     }
  177.     if( file ) {
  178.     fclose( file );
  179.     }
  180.     return( NULL );
  181. } /* gimmePicture */
  182.  
  183.  
  184. static ULONG makeBM( pic, myflags )
  185.     register PICTURE    *pic;
  186.     ULONG        myflags;
  187. {
  188.     UBYTE *plane;
  189.  
  190.     if( !(pic->bm = AllocMem((ULONG)sizeof(struct BitMap), MEMF_PUBLIC)) ) {
  191.     return( GBP_ERROR );
  192.     }
  193.     InitBitMap( pic->bm, (long) pic->bmh.nPlanes, (long) pic->bmh.w,
  194.             (long) pic->bmh.h );
  195.     return( gimmeBitPlanes(pic->bm, myflags) );
  196. } /* makeBM */
  197.  
  198.  
  199. short getRidOfPicture( picture )
  200.     PICTURE   *picture;
  201. {
  202. #ifdef GIMME_WIMPY
  203.     if( picture ) {
  204.     return( -1 );
  205.     }
  206. #endif
  207.     if( picture->colormap.ColorTable ) {
  208.     FreeMem( picture->colormap.ColorTable,
  209.             (ULONG) picture->colormap.Count * sizeof(USHORT) );
  210.     }
  211.     if( picture->bm ) {
  212.     getRidOfBitPlanes( picture->bm, picture->myflags );
  213.     FreeMem( picture->bm, (ULONG)sizeof(struct BitMap) );
  214.     }
  215.     chainFreeMem( picture->memhead );
  216.     return( 0 );
  217. } /* getRidOfPicture */
  218.  
  219.  
  220. short positionPicture( rp, myflags, pic, minterm, x, y )
  221.     struct RastPort *rp;
  222.     ULONG        myflags;
  223.     PICTURE        *pic;
  224.     SHORT        minterm;
  225.     register SHORT  x, y;
  226. {
  227.     SHORT        left, top;
  228.     SHORT        width, height;
  229.     SHORT        temp;
  230.     struct BitMap   *bm;
  231.  
  232. #ifdef GIMME_WIMPY
  233.     if( !pic || !rp ) {
  234.     return( -1 );
  235.     }
  236. #endif
  237.     left = top = 0;
  238.     width = pic->bmh.w;
  239.     height = pic->bmh.h;
  240.     bm = rp->BitMap;
  241.     switch( myflags & GPT_XFLAGS ) {
  242.       case GPT_XCENTRE:
  243.     x -= width >> 1;
  244.     break;
  245.       case GPT_XRIGHT:
  246.     x -= width;
  247.     break;
  248.       case GPT_XLEFT:
  249.       default:
  250.     break;
  251.     } /* switch */
  252.     switch( myflags & GPT_YFLAGS ) {
  253.       case GPT_YBOTTOM:
  254.       case GPT_YBASELINE:
  255.     y -= height;
  256.     break;
  257.       case GPT_YCENTRE:
  258.       case GPT_YCENTREBASE:
  259.     y -= height >> 1;
  260.     break;
  261.       case GPT_YTOP:
  262.       default:
  263.     break;
  264.     } /* switch */
  265.     if( minterm != GIM_MINTERM_DEST ) {
  266.     if( x < 0 ) {
  267.         width += x;
  268.         left -= x;
  269.         x = 0;
  270.     } else if( (temp = x + width - (bm->BytesPerRow << 3)) > 0 ) {
  271.         width -= temp;
  272.     }
  273.     if( y < 0 ) {
  274.         height += y;
  275.         top -= y;
  276.         y = 0;
  277.     } else if( (temp = y + height - bm->Rows) > 0 ) {
  278.         height -= temp;
  279.     }
  280.     if( width > 0 && height > 0 ) {
  281.         BltBitMapRastPort( pic->bm, (long) left, (long) top, rp,
  282.                 (long) x, (long) y,
  283.                 (long) width, (long) height, (long) minterm );
  284.     }
  285.     }
  286.     return( 0 );
  287. } /* positionPicture */
  288.  
  289.  
  290. short usePictureColors( pic, screen )
  291.     register PICTURE *pic;
  292.     struct Screen    *screen;
  293. {
  294. #ifdef GIMME_WIMPY
  295.     if( !pic || !screen ) {
  296.     return( -1 );
  297.     }
  298. #endif
  299.     return( setColors(screen, pic->colormap.ColorTable,
  300.             (SHORT) pic->colormap.Count) );
  301. } /* usePictureColors */
  302.  
  303.  
  304. /* read an IFF Id */
  305. static LONG getLong( file )
  306.     FILE    *file;
  307. {
  308.     register UBYTE  p[4];
  309.  
  310.     p[0] = GET(file);
  311.     p[1] = GET(file);
  312.     p[2] = GET(file);
  313.     p[3] = GET(file);
  314.     return( (LONG) Mk(p[0],p[1],p[2],p[3]) );
  315. } /* getLong */
  316.  
  317.  
  318. /* read an IFF chunk header */
  319. static getChunk( id, len, file )
  320.     LONG    *id, *len;
  321.     FILE    *file;
  322. {
  323.     *id = getId( file );
  324.     *len = getLen( file );
  325. } /* getChunk */
  326.  
  327.  
  328. /* get len bytes from the file and put them into memory */
  329. static memget( p, len, file )
  330.     UBYTE   *p;
  331.     LONG    len;
  332.     FILE    *file;
  333. {
  334.     for( ; len > 0L; len -= 0x07fffL, p += 0x07fffL ) {
  335.     fread( p, (int) (len & 0x07fffL), 1, file );
  336.     } /* for */
  337. } /* memget */
  338.  
  339.  
  340. /* get a word */
  341. static WORD getWord( file )
  342.     FILE    *file;
  343. {
  344.     WORD    v;
  345.  
  346.     v = GET(file) << 8;
  347.     return( v | GET(file) );
  348. } /* getWord */
  349.  
  350.  
  351. static int getCmpBody( bm, file )
  352.     struct BitMap   *bm;
  353.     FILE        *file;
  354. {
  355.     register short  x;
  356.     short        y, pl;
  357.     UBYTE        *plane;
  358.     UBYTE        run_len, verb_len, run_byte;
  359.     BYTE        v;
  360.     register BYTE   mybyte;
  361.  
  362.     verb_len = run_len = 0;
  363.     /* note: the bit-planes should be clear already */
  364.     for( y = 0; y < bm->Rows; ++y ) {
  365.     for( pl = 0; pl < bm->Depth; ++pl ) {
  366.         plane = bm->Planes[pl] + y * bm->BytesPerRow;
  367.         for( x = 0; x < bm->BytesPerRow; ++x ) {
  368.         if( run_len ) {
  369.             --run_len;
  370.             mybyte = run_byte;
  371.         } else if( verb_len ) {
  372.             --verb_len;
  373.             mybyte = GET(file);
  374.         } else if( (v = GET(file)) >= 0 ) {
  375.             verb_len = v;
  376.             mybyte = GET(file);
  377.         } else {
  378.             run_len = -v;
  379.             mybyte = run_byte = GET(file);
  380.         }
  381.         plane[x] = mybyte;
  382.         } /* for */
  383.     } /* for */
  384.     } /* for */
  385.     return( 0 );
  386. } /* getCmpBody */
  387.  
  388.  
  389. static int getBody( bm, flags, file )
  390.     register struct BitMap *bm;
  391.     ULONG   flags;
  392.     FILE    *file;
  393. {
  394.     register short  i;
  395.  
  396.     if( flags & GBP_CONTIGUOUS ) {
  397.     memget( bm->Planes[0], (ULONG)(bm->Depth) * bm->Rows * bm->BytesPerRow,
  398.             file );
  399.     } else {
  400.     for( i = 0; i < bm->Depth; ++i ) {
  401.         memget( bm->Planes[i], (ULONG)(bm->Rows) * bm->BytesPerRow, file );
  402.     } /* for */
  403.     }
  404.     return( 0 );
  405. } /* getBody */
  406.  
  407.  
  408. static int getLut( pic, len, file )
  409.     PICTURE *pic;
  410.     LONG    len;
  411.     FILE    *file;
  412. {
  413.     SHORT   i, ncols;
  414.     USHORT  red, green, blue;
  415.     USHORT   *lut;
  416.  
  417.     pic->colormap.Flags = pic->colormap.Type = 0;
  418.     ncols = len / 3;
  419.     lut = (USHORT *) AllocMem( (ULONG) ncols * sizeof(USHORT), MEMF_PUBLIC );
  420.     if( !lut ) {
  421.     return( -1 );
  422.     }
  423.     for( i = 0; i < ncols; ++i ) {
  424.     red = GET(file) >> 4;
  425.     green = GET(file) >> 4;
  426.     blue = GET(file) >> 4;
  427.     lut[i] = (red << 8) | (green << 4) | blue;
  428.     } /* for */
  429.     if( len & 1 ) {
  430.     GET(file);
  431.     }
  432.     pic->colormap.Count = ncols;
  433.     pic->colormap.ColorTable = (APTR) lut;
  434.     return( 0 );
  435. } /* getLut */
  436. SHAR_EOF
  437. cat << \SHAR_EOF > postext.c
  438. /*
  439.  *  FILE: postext.c
  440.  *  Support routines for writing text (or a number) in a rastport,
  441.  *  with flexible text location specification (eg any corner, centre).
  442.  *
  443.  *  Public Domain, but keep my name in it as the original author.
  444.  *  31-Aug-88    Jan Sven Trabandt   first release version
  445.  */
  446.  
  447.  
  448. #define I_AM_POSTEXT
  449. #include "gimmelib/gimmefuncs.h"
  450. #include "gimmelib/postext.h"
  451.  
  452.  
  453. SHORT positionText( rp, myflags, s, num, x, y )
  454.     register struct RastPort    *rp;
  455.     register ULONG        myflags;
  456.     UBYTE   *s;
  457.     LONG    num;
  458.     SHORT   x, y;
  459. {
  460.     register SHORT  i, j;
  461.     SHORT        len, rastlen, maxrastlen;
  462.     SHORT        maxbit, lowi;
  463.     SHORT        dest, temp;
  464.     SHORT        height, baseline;
  465.     struct RastPort myrp;
  466.     UBYTE        buf[12];        /* big enough for max ULONG + '\0' */
  467.  
  468.  
  469. #ifdef GIMME_WIMPY
  470.     if( !rp ) {
  471.     return( -1 );
  472.     }
  473. #endif
  474.     if( s ) {
  475.     len = strlen( s );
  476.     } else {
  477.     len = sprintf( buf, "%1ld", num );
  478.     s = buf;
  479.     }
  480.     maxrastlen = len * (rp->TxWidth + rp->TxSpacing);
  481.     rastlen = TextLength( rp, s, (long) len );
  482.  
  483.     if( myflags & (GPT_YUPWARDS | GPT_YDOWNWARDS) ) {
  484.     myrp = *rp;            /* copy struct */
  485.     myrp.BitMap = gimmeBitMap( rp->BitMap->Depth, rastlen, myrp.TxHeight );
  486.     if( !myrp.BitMap ) {
  487.         return( -1 );
  488.     }
  489.     myrp.Layer = NULL;        /* make sure no layer else trouble */
  490.     myrp.GelsInfo = NULL;
  491.     Move( &myrp, 0L, (long) myrp.TxBaseline );
  492.     Text( &myrp, s, (long) len );
  493.  
  494.     maxbit = rastlen - 1;
  495.     switch( myflags & GPT_XFLAGS ) {
  496.       case GPT_XRIGHT:
  497.         if( myflags & GPT_YDOWNWARDS ) {
  498.         y -= maxbit;
  499.         }
  500.         break;
  501.       case GPT_XCENTRE:
  502.         y -= rastlen >> 1;
  503.         break;
  504.       case GPT_XLEFT:
  505.       default:
  506.         if( myflags & GPT_YUPWARDS ) {
  507.         y -= maxbit;
  508.         }
  509.         break;
  510.     } /* switch */
  511.  
  512.     if( myflags & GPT_XTHICKEN ) {              /* if double thickness */
  513.         height = (myrp.TxHeight << 1) - 1;
  514.         baseline = (myrp.TxBaseline << 1);
  515.     } else {
  516.         height = myrp.TxHeight - 1;
  517.         baseline = myrp.TxBaseline;
  518.     }
  519.  
  520.     switch( myflags & GPT_YFLAGS ) {        /* make x top of char */
  521.       case GPT_YBOTTOM:
  522.         if( myflags & GPT_YUPWARDS ) {
  523.         x -= height;
  524.         }
  525.         break;
  526.       case GPT_YCENTRE:            /* skew to top of char */
  527.         if( myflags & GPT_YDOWNWARDS ) {
  528.         /* x += (height >> 1) - height; */
  529.         x -= (height + 1) >> 1;
  530.         } else {
  531.         x -= height >> 1;
  532.         }
  533.         break;
  534.       case GPT_YCENTREBASE:         /* skew to bottom of char */
  535.         if( myflags & GPT_YDOWNWARDS ) {
  536.         x += ((baseline + 1) >> 1) - height;
  537.         } else {
  538.         x -= (baseline + 1) >> 1;
  539.         }
  540.         break;
  541.       case GPT_YTOP:
  542.         if( myflags & GPT_YDOWNWARDS ) {
  543.         x -= height;
  544.         }
  545.         break;
  546.       case GPT_YBASELINE:
  547.       default:
  548.         if( myflags & GPT_YDOWNWARDS ) {
  549.         x += baseline - height;
  550.         } else {
  551.         x -= baseline;
  552.         }
  553.         break;
  554.     } /* switch */
  555.  
  556.     if( y < 0 ) {
  557.         rastlen += y;
  558.         y = 0;
  559.     }
  560.     lowi = rastlen - rp->BitMap->Rows;
  561.     if( lowi > 0 ) {
  562.         rastlen -= lowi;
  563.     } else {
  564.         lowi = 0;
  565.     }
  566.     maxbit = rastlen - 1;
  567.     if( myflags & GPT_YDOWNWARDS ) {
  568.         if( lowi ) {
  569.         maxbit -= lowi;
  570.         lowi = 0;
  571.         }
  572.         temp = x + height;
  573.         for( j = myrp.TxHeight - 1; j >= 0; --j ) {
  574.         if( GPT_XTHICKEN ) {
  575.             dest = temp - (j << 1) - 1;
  576.         } else {
  577.             dest = temp - j;
  578.         }
  579.         for( i = maxbit; i >= lowi; --i ) {
  580.             /* if no error and not background colour */
  581.             if( ReadPixel(&myrp, (long) i, (long) j) > 0L ) {
  582.             WritePixel( rp, (long) dest, (long) y + i );
  583.             if( myflags & GPT_XTHICKEN ) {
  584.                 WritePixel( rp, (long) dest + 1, (long) y + i );
  585.             }
  586.             }
  587.         } /* for */
  588.         } /* for */
  589.     } else {        /* else upwards */
  590.         for( i = maxbit; i >= lowi; --i ) {
  591.         dest = y + maxbit - i;
  592.         for( j = myrp.TxHeight - 1; j >= 0; --j ) {
  593.             /* if no error and not background colour */
  594.             if( ReadPixel(&myrp, (long) i, (long) j) > 0L ) {
  595.             if( myflags & GPT_XTHICKEN ) {
  596.                 temp = j << 1;
  597.                 WritePixel( rp, (long) x + temp + 1, (long) dest );
  598.                 WritePixel( rp, (long) x + temp, (long) dest );
  599.             } else {
  600.                 WritePixel( rp, (long) x + j, (long) dest );
  601.             }
  602.             }
  603.         } /* for */
  604.         } /* for */
  605.     }
  606.     getRidOfBitMap( myrp.BitMap );
  607.     } else {
  608.     switch( myflags & GPT_XFLAGS ) {
  609.       case GPT_XRIGHT:
  610.         x -= rastlen - 1;
  611.         break;
  612.       case GPT_XCENTRE:
  613.         x -= rastlen >> 1;
  614.         break;
  615.       case GPT_XLEFT:
  616.       default:
  617.         break;
  618.     } /* switch */
  619.  
  620.     switch( myflags & GPT_YFLAGS ) {        /* make y top of char */
  621.       case GPT_YBOTTOM:
  622.         y -= rp->TxHeight - 1;
  623.         break;
  624.       case GPT_YCENTRE:
  625.         y -= (rp->TxHeight - 1) >> 1;       /* skew to top of char */
  626.         break;
  627.       case GPT_YCENTREBASE:
  628.         y -= (rp->TxBaseline + 1) >> 1;     /* skew to bottom of char */
  629.         break;
  630.       case GPT_YTOP:
  631.         break;
  632.       case GPT_YBASELINE:
  633.       default:
  634.         y -= rp->TxBaseline;
  635.         break;
  636.     } /* switch */
  637.     y += rp->TxBaseline;        /* adjust top to baseline for Text() */
  638.     /* note rp's TxBaseline is offset from top pixel of character */
  639.  
  640.     Move( rp, (long) x, (long) y );
  641.     Text( rp, s, (long) len );
  642.     }
  643.     return( maxrastlen );
  644. } /* positionText */
  645. SHAR_EOF
  646. cat << \SHAR_EOF > requester.c
  647. /*
  648.  *  FILE: requester.c
  649.  *  Support routines for putting up an Auto Request or creating a Requester.
  650.  *
  651.  *  Public Domain, but keep my name in it as the original author.
  652.  *  31-Aug-88    Jan Sven Trabandt   first release version
  653.  *  31-Oct-88    Jan Sven Trabandt   added more functionality to gimmeRequester
  654.  */
  655.  
  656.  
  657. #define I_AM_REQUESTER
  658. #include <clib/macros.h>
  659. #include "gimmelib/gimmefuncs.h"
  660. #include "gimmelib/requester.h"
  661. #include "gimmelib/macros.h"
  662.  
  663. extern struct GfxBase *GfxBase;
  664.  
  665.  
  666. SHORT gimmeAutoRequest( window, s, textattr )
  667.     struct Window   *window;
  668.     UBYTE        *s;
  669.     struct TextAttr *textattr;
  670. {
  671.     struct IntuiText    itext, ptext, ntext;
  672.     SHORT        xsize, ysize, width;
  673.  
  674.     if( !s ) {
  675.     s = (UBYTE *) GAR_DUMMY_TEXT;
  676.     }
  677.     itext.FrontPen  = AUTOFRONTPEN;
  678.     itext.BackPen   = AUTOBACKPEN;
  679.     itext.DrawMode  = AUTODRAWMODE;
  680.     itext.LeftEdge  = AUTOLEFTEDGE;
  681.     itext.TopEdge   = AUTOTOPEDGE;
  682.     itext.ITextFont = textattr;
  683.     itext.IText     = s;
  684.     itext.NextText  = AUTONEXTTEXT;
  685.  
  686.     ptext = itext;        /* struct copy */
  687.     ntext = itext;        /* struct copy */
  688.     ptext.IText = gimAutReqPostext;
  689.     ntext.IText = gimAutReqNegtext;
  690.     xsize = 0;
  691.     if( textattr ) {
  692.     ysize = textattr->ta_YSize;
  693.     } else if( window ) {
  694.     ysize = window->RPort->TxHeight;
  695.     xsize = window->RPort->TxWidth;
  696.     } else {
  697.     ysize = GfxBase->DefaultFont->tf_YSize;
  698.     }
  699.     if( !xsize ) {
  700.     xsize = GfxBase->DefaultFont->tf_XSize;
  701.     }
  702.     width = MAX(IntuiTextLength(&itext),
  703.         IntuiTextLength(&ptext) + IntuiTextLength(&ntext) + 3*xsize);
  704.     return (
  705.         AutoRequest( window, &itext, &ptext, &ntext, ENDGADGET, ENDGADGET,
  706.             (ULONG) width + xsize * GAR_BORDER_WIDTH,
  707.             (ULONG) ysize * GAR_HEIGHT )
  708.     );
  709. } /* gimmeAutoRequest */
  710.  
  711.  
  712. #define XLEEWAY     8        /* border space */
  713. #define YLEEWAY     4
  714. #define MIN_WIDTH   50        /* minimum dimensions if calculating dimension(s) */
  715. #define MIN_HEIGHT  20        /* not counting y leeways */
  716.  
  717. struct Requester *gimmeRequester( mh, left, top, width, height, backfill,
  718.                     gp, s, textattr, flags )
  719.     void        **mh;
  720.     SHORT        left, top;
  721.     SHORT        width, height;
  722.     UBYTE        backfill;
  723.     struct Gadget   *gp;
  724.     UBYTE        *s;
  725.     struct TextAttr *textattr;
  726.     ULONG        flags;
  727. {
  728.     register struct Requester    *req;
  729.     register struct Border    *bp;
  730.     struct Gadget   *gadg;
  731.     SHORT   len, extra;
  732.     void    *mymh = NULL;
  733.  
  734.     GUESS
  735.     QUIF( !mh );
  736.     req = chainAllocMem( &mymh, (ULONG)sizeof(struct Requester),
  737.                 MEMF_PUBLIC | MEMF_CLEAR );
  738.     QUIF( !req );
  739.     if( flags & POINTREL ) {
  740.         req->RelLeft = left;
  741.         req->RelTop = top;
  742.     }
  743.     req->LeftEdge = left;
  744.     req->TopEdge = top;
  745.     req->ReqGadget = gp;
  746.     req->ReqText = gimmeIntuiText( &mymh, s != NULL ? s : (UBYTE *)"",
  747.                     textattr, 0 );
  748.     QUIF( !req->ReqText );
  749.     req->ReqText->TopEdge = YLEEWAY;
  750.     req->ReqText->LeftEdge = XLEEWAY;
  751.     req->ReqText->BackPen = backfill;
  752.     req->Flags = flags;
  753.     req->BackFill = backfill;
  754.     if( width <= 0 ) {
  755.         width = IntuiTextLength( req->ReqText );
  756.         extra = 0;
  757.         for( gadg = gp; gadg; gadg = gadg->NextGadget ) {
  758.         if( gadg->Flags & GRELRIGHT ) {
  759.             len = -gadg->LeftEdge;
  760.         } else {
  761.             len = gadg->LeftEdge;
  762.         }
  763.         if( !(gadg->Flags & GRELWIDTH) ) {
  764.             len += gadg->Width;
  765.         }
  766.         if( len > width ) {
  767.             width = len;
  768.         } else if( gadg->Activation & (RIGHTBORDER | LEFTBORDER) ) {
  769.             if( len > extra ) {
  770.             extra = gadg->Width;
  771.             }
  772.         }
  773.         } /* for */
  774.         width += extra + XLEEWAY;
  775.         if( width <= 0 ) {
  776.         width = MIN_WIDTH;
  777.         }
  778.     }
  779.     req->Width = width;
  780.     if( height <= 0 ) {
  781.         if( textattr ) {
  782.         height = textattr->ta_YSize;
  783.         } else {
  784.         height = MIN_HEIGHT;
  785.         }
  786.         extra = 0;
  787.         for( gadg = gp; gadg; gadg = gadg->NextGadget ) {
  788.         if( gadg->Flags & GRELBOTTOM ) {
  789.             len = -gadg->TopEdge;
  790.         } else {
  791.             len = gadg->TopEdge;
  792.         }
  793.         if( !(gadg->Flags & GRELHEIGHT) ) {
  794.             len += gadg->Height;
  795.         }
  796.         if( len > height ) {
  797.             height = len;
  798.         } else if( gadg->Activation & (BOTTOMBORDER | TOPBORDER) ) {
  799.             if( len > extra ) {
  800.             extra = gadg->Height;
  801.             }
  802.         }
  803.         } /* for */
  804.         height += extra + YLEEWAY;
  805.     }
  806.     req->Height = height;
  807.     bp = gimmeBorder( &mymh, width - 4, height - 2 );
  808.     if( bp ) {
  809.         bp->LeftEdge = 2;
  810.         bp->TopEdge = 1;
  811.         bp->FrontPen = ~backfill;
  812.         req->ReqBorder = bp;
  813.         /* double thickness vertical lines */
  814.         bp = gimmeBorder( &mymh, width - 6, height - 2 );
  815.         if( bp ) {
  816.         bp->LeftEdge = 3;
  817.         bp->TopEdge = 1;
  818.         bp->FrontPen = ~backfill;
  819.         req->ReqBorder->NextBorder = bp;
  820.         }
  821.     }
  822.     linkChainMem( mh, mymh );
  823.     return( req );
  824.     ENDGUESS
  825.     if( mymh ) {
  826.     chainFreeMem( mymh );
  827.     }
  828.     return( NULL );
  829. } /* gimmeRequester */
  830. SHAR_EOF
  831. cat << \SHAR_EOF > screen.c
  832. /*
  833.  *  FILE: screen.c
  834.  *  Support for Intuition screen stuff.
  835.  *
  836.  *  Public Domain, but keep our names in it as the original authors.
  837.  *  31-Aug-88    Jan Sven Trabandt   first release version
  838.  *  30-Sep-88    Jan Sven Trabandt   gimmeNewScreen checks width more closely
  839.  */
  840.  
  841.  
  842. #define I_AM_SCREEN
  843. #include "gimmelib/gimmefuncs.h"
  844. #include "gimmelib/window.h"
  845. #include "gimmelib/globals.h"
  846.  
  847. extern struct GfxBase *GfxBase;
  848.  
  849.  
  850. struct NewScreen *gimmeNewScreen( modes, type, depth, title, textattr )
  851.     ULONG        modes, type;
  852.     SHORT        depth;
  853.     UBYTE        *title;
  854.     struct TextAttr *textattr;
  855. {
  856.     register struct NewScreen    *ns;
  857.  
  858. #ifdef GIMME_WIMPY
  859.     if( depth < 1 || depth > 8 ) {
  860.     return( NULL );
  861.     }
  862. #endif
  863.     ns = (struct NewScreen *) AllocMem( (ULONG)sizeof(struct NewScreen),
  864.                         MEMF_PUBLIC | MEMF_CLEAR );
  865.     if( ns ) {
  866.     ns->Width = GfxBase->NormalDisplayColumns;
  867.     if( modes & HIRES ) {
  868.         if( ns->Width <= 350 ) {
  869.         ns->Width <<= 1;
  870.         }
  871.     } else {
  872.         if( ns->Width > 350 ) {
  873.         ns->Width >>= 1;
  874.         }
  875.     }
  876.     ns->Height = STDSCREENHEIGHT;
  877.     ns->Depth = depth;
  878.     ns->BlockPen = 1;
  879.     ns->ViewModes = modes;
  880.     ns->Type = type;
  881.     ns->Font = textattr;
  882.     ns->DefaultTitle = title;
  883.     }
  884.     return( ns );
  885. } /* gimmeNewScreen */
  886.  
  887.  
  888. short getRidOfNewScreen( ns )
  889.     struct NewScreen    *ns;
  890. {
  891. #ifdef GIMME_WIMPY
  892.     if( !ns ) {
  893.     return( -1 );
  894.     }
  895. #endif
  896.     FreeMem( ns, (ULONG)sizeof(struct NewScreen) );
  897.     return( 0 );
  898. } /* getRidOfNewScreen */
  899.  
  900.  
  901. struct Screen *gimmeScreen( ns, winptr, depth, IDCMPflags, winflags )
  902.     struct NewScreen    *ns;
  903.     struct Window    **winptr;
  904.     SHORT        depth;
  905.     ULONG        IDCMPflags, winflags;
  906. {
  907.     struct Screen    *screen;
  908.     struct NewWindow    *nw;
  909.     struct NewScreen    *myns;
  910.  
  911.     if( !(myns = ns) ) {
  912.     ns = gimmeNewScreen( HIRES, CUSTOMSCREEN, depth, NULL, &gimMyFont );
  913.     }
  914.     if( ns ) {
  915.     screen = OpenScreen( ns );
  916.     if( screen && winptr ) {
  917.         nw = gimmeNewWindow( NULL, screen, 0, 1, IDCMPflags, winflags );
  918.         if( !nw ) {
  919.         *winptr = NULL;
  920.         } else {
  921.         *winptr = gimmeWindow( nw, 0, 0, 0 );
  922.         getRidOfNewWindow( nw );
  923.         if( !*winptr ) {
  924.             getRidOfScreen( screen, NULL );
  925.             screen = NULL;
  926.         } else {
  927.             ShowTitle( screen, FALSE );     /* hide screen title */
  928.         }
  929.         }
  930.     }
  931.     }
  932.     if( !myns && ns ) {
  933.     getRidOfNewScreen( ns );
  934.     }
  935.     return( screen );
  936. } /* gimmeScreen */
  937.  
  938.  
  939. struct Screen *gimmeScreenLazy( ns, winptr, depth )
  940.     struct NewScreen    *ns;
  941.     struct Window    **winptr;
  942.     SHORT        depth;
  943. {
  944.     return( gimmeScreen(ns, winptr, depth, IDCMP_DEFAULT, FLAGS_DEFAULT) );
  945. } /* gimmeScreenLazy */
  946.  
  947.  
  948. short getRidOfScreen( screen, window )
  949.     struct Screen   *screen;
  950.     struct Window   *window;
  951. {
  952.     if( window ) {
  953.     getRidOfWindow( window );
  954.     }
  955.     if( screen ) {
  956.     CloseScreen( screen );
  957.     }
  958.     return( 0 );
  959. } /* getRidOfScreen */
  960.  
  961.  
  962. short lowerScreen( screen, toheight )
  963.     struct Screen   *screen;
  964.     SHORT        toheight;
  965. {
  966.     register SHORT  i;
  967.  
  968. #ifdef GIMME_WIMPY
  969.     if( !screen ) {
  970.     return( -1 );
  971.     }
  972. #endif
  973.     for( i = screen->TopEdge | 1; i < toheight; i += 2 ) {
  974.     MoveScreen( screen, 0L, 2L );
  975.     } /* for */
  976.     return( 0 );
  977. } /* lowerScreen */
  978.  
  979.  
  980. short raiseScreen( screen, toheight )
  981.     struct Screen   *screen;
  982.     SHORT        toheight;
  983. {
  984.     register SHORT  i;
  985.  
  986. #ifdef GIMME_WIMPY
  987.     if( !screen ) {
  988.     return( -1 );
  989.     }
  990. #endif
  991.     for( i = screen->TopEdge & (~1); i >= toheight; i -= 2 ) {
  992.     MoveScreen( screen, 0L, -2L );
  993.     } /* for */
  994.     return( 0 );
  995. } /* raiseScreen */
  996. SHAR_EOF
  997. cat << \SHAR_EOF > scrollbar.c
  998. /*
  999.  *  FILE: scrollbar.c
  1000.  *  Support routines for making scroll-bar and -button gadgets.
  1001.  *
  1002.  *  Public Domain, but keep my name in it as the original author.
  1003.  *  31-Aug-88    Jan Sven Trabandt   first release version
  1004.  *  30-Sep-88    Jan Sven Trabandt   keep up with changes to gadget.c
  1005.  */
  1006.  
  1007.  
  1008. #define I_AM_SCROLLBAR
  1009. #include "gimmelib/gimmefuncs.h"
  1010. #include "gimmelib/scrollbar.h"
  1011. #include "gimmelib/macros.h"
  1012.  
  1013.  
  1014. struct Gadget *gimmeOneScroll( window, id, dirflags, myflags )
  1015.     struct Window   *window;
  1016.     USHORT        id;
  1017.     ULONG        dirflags, myflags;
  1018. {
  1019.     register struct Gadget  *gp;
  1020.     void    *gadgmh = NULL;
  1021.     USHORT  *data;
  1022.     USHORT  *imagedata;
  1023.  
  1024.     GUESS
  1025.     QUIF( !id );
  1026.     gp = chainAllocMem( &gadgmh, (ULONG)sizeof(struct Gadget),
  1027.                 MEMF_CLEAR | MEMF_PUBLIC );
  1028.     QUIF( !gp );
  1029.     gp->GadgetType = BOOLGADGET;
  1030.     gp->GadgetRender = (APTR) gimmeImage( &gadgmh, GOS_BITDEPTH,
  1031.                         GOS_BITWIDTH, GOS_BITHEIGHT );
  1032.     QUIF( !gp->GadgetRender );
  1033.  
  1034.     if( dirflags & FREEVERT ) {
  1035.         gp->LeftEdge = -(GOS_BITWIDTH -1);
  1036.         gp->Width = GOS_BITWIDTH;
  1037.         gp->Height = GOS_BITHEIGHT;
  1038.         if( myflags & GOS_TOP ) {
  1039.         if( window ) {
  1040.             gp->TopEdge = window->BorderTop - 1;
  1041.         } else {
  1042.             gp->TopEdge = GIM_DFLT_TBHEIGHT;
  1043.         }
  1044.         gp->Flags = GADGIMAGE | GADGHCOMP | GRELRIGHT;
  1045.         imagedata = gimDataOneScrollUp;
  1046.         } else {
  1047.         gp->TopEdge = -GIM_SZHEIGHT - (GOS_BITHEIGHT -1);
  1048.         gp->Flags = GADGIMAGE | GADGHCOMP | GRELRIGHT | GRELBOTTOM;
  1049.         imagedata = gimDataOneScrollDown;
  1050.         }
  1051.         gp->Activation = RELVERIFY | RIGHTBORDER;
  1052.     } else {        /* otherwise we have FREEHORIZ */
  1053.         gp->TopEdge = -(GOS_BITHEIGHT -1);
  1054.         gp->Width = GOS_BITWIDTH;
  1055.         gp->Height = GOS_BITHEIGHT;
  1056.         if( myflags & GOS_LEFT ) {
  1057.         gp->LeftEdge = 0;
  1058.         gp->Flags = GADGIMAGE | GADGHCOMP | GRELBOTTOM;
  1059.         imagedata = gimDataOneScrollLeft;
  1060.         } else {
  1061.         gp->LeftEdge = -GIM_SZWIDTH - (GOS_BITWIDTH - 1);
  1062.         gp->Flags = GADGIMAGE | GADGHCOMP | GRELBOTTOM | GRELRIGHT;
  1063.         imagedata = gimDataOneScrollRight;
  1064.         }
  1065.         gp->Activation = RELVERIFY | BOTTOMBORDER;
  1066.     }
  1067.     copyDataImage( imagedata, (struct Image *) gp->GadgetRender );
  1068.     if( window ) {
  1069.         if( window->Flags & GIMMEZEROZERO ) {
  1070.         gp->GadgetType |= GZZGADGET;
  1071.         }
  1072.     }
  1073.     gp->GadgetID = id;
  1074.     gp->UserData = gadgmh;
  1075.     return( gp );
  1076.     ENDGUESS
  1077.     if( gadgmh ) {
  1078.     chainFreeMem( gadgmh );
  1079.     return( NULL );
  1080.     }
  1081. } /* gimmeOneScroll */
  1082.  
  1083.  
  1084. struct Gadget *gimmeScrollBar( window, id, propflags, myflags )
  1085.     struct Window   *window;
  1086.     USHORT        id;
  1087.     ULONG        propflags, myflags;
  1088. {
  1089.     register struct Gadget  *gp;
  1090.     SHORT   ones_size = 0;
  1091.     SHORT   left, top, width, height;
  1092.     ULONG   gadgflags, activation;
  1093.     void    *gadgmh = NULL;
  1094.  
  1095.     GUESS
  1096.     QUIF( !id );
  1097.     if( propflags & FREEVERT ) {
  1098.         propflags &= ~FREEHORIZ;
  1099.         if( myflags & GSB_ONE_SCROLL ) {
  1100.         ones_size = GOS_BITHEIGHT;
  1101.         }
  1102.         left = - (GOS_BITWIDTH -1);
  1103.         top  = ones_size;
  1104.         if( !(myflags & GSB_NO_TITLEBAR) ) {
  1105.         if( window ) {
  1106.             top += window->BorderTop - 1;
  1107.         } else {
  1108.             top += GIM_DFLT_TBHEIGHT;
  1109.         }
  1110.         }
  1111.         width  = GOS_BITWIDTH;
  1112.         height = -top - ones_size - GIM_SZHEIGHT;
  1113.         gadgflags  = GADGHCOMP | GADGIMAGE | GRELRIGHT | GRELHEIGHT;
  1114.         activation = RELVERIFY | RIGHTBORDER;
  1115.     } else {        /* otherwise we have FREEHORIZ */
  1116.         propflags &= ~FREEVERT;
  1117.         if( myflags & GSB_ONE_SCROLL ) {
  1118.         ones_size = GOS_BITWIDTH;
  1119.         }
  1120.         left = ones_size;
  1121.         top  = - (GOS_BITHEIGHT -1);
  1122.         width  = -GIM_SZWIDTH - (ones_size<<1);
  1123.         height = GOS_BITHEIGHT;
  1124.         gadgflags  = GADGHCOMP | GADGIMAGE | GRELBOTTOM | GRELWIDTH;
  1125.         activation = RELVERIFY | BOTTOMBORDER;
  1126.     }
  1127.     gp = gimmePropGadget( window, id, left, top, width, height, NULL,
  1128.                 NULL, activation, propflags );
  1129.     QUIF( !gp );
  1130.     gp->Flags = gadgflags;
  1131.     if( window ) {
  1132.         ((struct PropInfo *)gp->SpecialInfo)->VertBody =
  1133.                 0x0FFFFL * window->Height / window->MaxHeight;
  1134.         ((struct PropInfo *)gp->SpecialInfo)->HorizBody =
  1135.                 0x0FFFFL * window->Width / window->MaxWidth;
  1136.     }
  1137.     linkChainMem( &gp->UserData, gadgmh );
  1138.     return( gp );
  1139.     ENDGUESS
  1140.     if( gadgmh ) {
  1141.     chainFreeMem( gadgmh );
  1142.     return( NULL );
  1143.     }
  1144. } /* gimmeScrollBar */
  1145.  
  1146.  
  1147. struct Gadget *gimmeFullScrollBar( window, id, propflags, myflags, id1, id2 )
  1148.     struct Window   *window;
  1149.     USHORT        id;
  1150.     ULONG        propflags, myflags;
  1151.     USHORT        id1, id2;
  1152. {
  1153.     register struct Gadget  *gp;
  1154.  
  1155.     GUESS
  1156.     QUIF( !id );
  1157.     gp = gimmeScrollBar( window, id, propflags, myflags | GSB_ONE_SCROLL );
  1158.     QUIF( !gp );
  1159.     /* top or left one-scroll */
  1160.     gp->NextGadget = gimmeOneScroll( window, id1, propflags,
  1161.                         GOS_TOP | GOS_LEFT );
  1162.     QUIF( !gp->NextGadget );
  1163.     /* bottom or right one-scroll */
  1164.     gp->NextGadget->NextGadget = gimmeOneScroll( window, id2, propflags,
  1165.                         GOS_BOT | GOS_RIGHT );
  1166.     QUIF( !gp->NextGadget->NextGadget );
  1167.     return( gp );
  1168.     ENDGUESS
  1169.     if( gp ) {
  1170.     getRidOfGadgets( gp );
  1171.     }
  1172.     return( NULL );
  1173. } /* gimmeFullScrollBar */
  1174. SHAR_EOF
  1175. cat << \SHAR_EOF > sound.c
  1176. /*
  1177.  *  FILE: sound.c
  1178.  *  Support routines for reading IFF/8SVX files.
  1179.  *
  1180.  *  Public Domain, but keep our names in it as the original authors.
  1181.  *  09-Dec-87    Rico Mariani        original code (modified by JST)
  1182.  *  31-Aug-88    Jan Sven Trabandt   first release version
  1183.  */
  1184.  
  1185.  
  1186. #define I_AM_SOUND
  1187. #include "gimmelib/gimmefuncs.h"
  1188. #include "gimmelib/sound.h"
  1189. #include <stdio.h>
  1190.  
  1191.  
  1192. #define GET(iffile)         getc( iffile )
  1193.  
  1194. #define getId            getLong
  1195. #define getLen            getLong
  1196. #define getByte         GET
  1197. #define skip(len, file)     fseek(file, (long)(len), 1)
  1198.  
  1199. #define getV8H(v8h, file)   fread(v8h, sizeof(Voice8Header), 1, file)
  1200.  
  1201. /* requires an existent variable 'char *errmsg' and a label 'failure_return' */
  1202. #define fail_and_return(msg)    {errmsg = msg; goto failure_return;}
  1203.  
  1204. /* forward declarations */
  1205. static LONG getLong();
  1206. static WORD getWord();
  1207.  
  1208. static char noMemMsg[] = "insufficient memory\n";
  1209. static char badFileMsg[] = "corrupt or incomplete file\n";
  1210.  
  1211.  
  1212. SOUND *gimmeSound( filename )
  1213.     UBYTE   *filename;
  1214. {
  1215.     LONG    len, id;
  1216.     SOUND   *snd = NULL;
  1217.     BYTE    *p;
  1218.     void    *mh = NULL;
  1219.     FILE    *file = NULL;
  1220.     char    *errmsg = " ";
  1221.     SHORT   i;
  1222.  
  1223.     if( !(file = fopen(filename, "r")) ) {
  1224.     fail_and_return( "unable to open iff sound file for read\n" );
  1225.     }
  1226.     if( getId(file) != ID_FORM ) {
  1227.     fail_and_return( "not IFF format\n" );
  1228.     }
  1229.     getLen( file );
  1230.     if( getId(file) != ID_8SVX ) {
  1231.     fail_and_return( "not 8SVX format\n" );
  1232.     }
  1233.     for( ;; ) {
  1234.     getChunk( &id, &len, file );
  1235.     if( ferror(file) || feof(file) ) {
  1236.         fail_and_return( badFileMsg );
  1237.     }
  1238.     switch( id ) {
  1239.       case ID_VHDR:
  1240.         snd = chainAllocMem( &mh, (ULONG)sizeof(SOUND),
  1241.                     MEMF_PUBLIC | MEMF_CLEAR );
  1242.         if( !snd ) {
  1243.            fail_and_return( noMemMsg );
  1244.         }
  1245.         getV8H( &snd->vh, file );
  1246.         if( len & 1 ) {
  1247.         GET(file);
  1248.         }
  1249.         break;
  1250.       case ID_BODY:
  1251.         if( !snd ) {
  1252.         fail_and_return( "didn't find VHDR chunk\n" );
  1253.         }
  1254.         switch( snd->vh.sCompression ) {
  1255.           case sCmpNone:
  1256.         snd->bodylen = len;
  1257.         snd->body = chainAllocMem( &mh, len, MEMF_CHIP );
  1258.         if( !snd->body ) {
  1259.             fail_and_return( noMemMsg );
  1260.         }
  1261.         memget( snd->body, len, file );
  1262.         break;
  1263.           case sCmpFibDelta:
  1264.         snd->bodylen = len << 1;
  1265.         snd->body = chainAllocMem( &mh, (ULONG) snd->bodylen,
  1266.                         MEMF_CHIP );
  1267.         if( !snd->body ) {
  1268.             fail_and_return( noMemMsg );
  1269.         }
  1270.         p = AllocMem( len, MEMF_PUBLIC );
  1271.         if( !p ) {
  1272.             fail_and_return( noMemMsg );
  1273.         }
  1274.         memget( p, len, file );
  1275.         DUnpack( p, len, snd->body );
  1276.         FreeMem( p, len );
  1277.         break;
  1278.           default:
  1279.         fail_and_return( "unknown compression form\n" );
  1280.         break;
  1281.         } /* switch */
  1282.         if( len & 1 ) {
  1283.         GET(file);
  1284.         }
  1285.         if( ferror(file) ) {
  1286.         fail_and_return( badFileMsg );
  1287.         }
  1288.         snd->memhead = mh;
  1289.         fclose( file );
  1290.         return( snd );
  1291.         break;
  1292.       case ID_NAME:
  1293.       case ID_AUTH:
  1294.       case ID_COPY:
  1295.       case ID_ANNO:
  1296.       case ID_ATAK:
  1297.       case ID_RLSE:
  1298.       default:        /* unimplemented chunk type */
  1299.         skip( EVEN(len), file );
  1300.         break;
  1301.     } /* switch */
  1302.     } /* for */
  1303. failure_return: {}
  1304.     if( Output() ) {
  1305.     Write( Output(), errmsg, (ULONG)strlen(errmsg) );
  1306.     }
  1307.     if( mh ) {
  1308.     chainFreeMem( mh );
  1309.     }
  1310.     if( file ) {
  1311.     fclose( file );
  1312.     }
  1313.     return( NULL );
  1314. } /* gimmeSound */
  1315.  
  1316.  
  1317. short getRidOfSound( sound )
  1318.     SOUND   *sound;
  1319. {
  1320. #ifdef GIMME_WIMPY
  1321.     if( !sound ) {
  1322.     return( -1 );
  1323.     }
  1324. #endif
  1325.     chainFreeMem( sound->memhead );
  1326.     return( 0 );
  1327. } /* getRidOfSound */
  1328.  
  1329.  
  1330. /* read an IFF Id */
  1331. static LONG getLong( file )
  1332.     FILE    *file;
  1333. {
  1334.     register UBYTE  p[4];
  1335.  
  1336.     p[0] = GET(file);
  1337.     p[1] = GET(file);
  1338.     p[2] = GET(file);
  1339.     p[3] = GET(file);
  1340.     return( (LONG) Mk(p[0],p[1],p[2],p[3]) );
  1341. } /* getLong */
  1342.  
  1343.  
  1344. /* read an IFF chunk header */
  1345. static getChunk( id, len, file )
  1346.     LONG    *id, *len;
  1347.     FILE    *file;
  1348. {
  1349.     *id = getId( file );
  1350.     *len = getLen( file );
  1351. } /* getChunk */
  1352.  
  1353.  
  1354. /* get len bytes from the file and put them into memory */
  1355. static memget( p, len, file )
  1356.     UBYTE   *p;
  1357.     LONG    len;
  1358.     FILE    *file;
  1359. {
  1360.     for( ; len > 0L; len -= 0x07fffL, p += 0x07fffL ) {
  1361.     fread( p, (int) (len & 0x07fffL), 1, file );
  1362.     } /* for */
  1363. } /* memget */
  1364.  
  1365.  
  1366. /* get a word */
  1367. static WORD getWord( file )
  1368.     FILE    *file;
  1369. {
  1370.     WORD    v;
  1371.  
  1372.     v = GET(file) << 8;
  1373.     return( v | GET(file) );
  1374. } /* getWord */
  1375.  
  1376.  
  1377. /* get the EGPoint info */
  1378. static getEGPoint( pnt, file )
  1379.     EGPoint *pnt;
  1380.     FILE    *file;
  1381. {
  1382.     pnt->duration = getWord( file );
  1383.     pnt->dest = getLong( file );
  1384. } /* getEGPoint */
  1385.  
  1386.  
  1387. static BYTE codeToDelta[] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};
  1388.  
  1389. /* unpack a part of a fibonacci delta encoded sound sample */
  1390. static BYTE D1Unpack( source, n, dest, x )
  1391.     BYTE    *source;
  1392.     LONG    n;
  1393.     BYTE    *dest;
  1394.     BYTE    x;
  1395. {
  1396.     UBYTE   d;
  1397.     LONG    i, lim;
  1398.  
  1399.     lim = n << 1;
  1400.     for( i = 0; i < lim; ++i ) {
  1401.     d = source[i>>1];
  1402.     if( i & 1 ) {
  1403.         d &= 0xf;
  1404.     } else {
  1405.         d >>= 4;
  1406.     }
  1407.     x += codeToDelta[d];
  1408.     dest[i] = x;
  1409.     } /* for */
  1410.     return( x );                /* return last data value */
  1411. } /* D1Unpack */
  1412.  
  1413.  
  1414. /* unpack a fibonacci delta encoded sound sample */
  1415. static DUnpack( source, n, dest )
  1416.     BYTE    *source;
  1417.     LONG    n;
  1418.     BYTE    *dest;
  1419. {
  1420.     D1Unpack( source + 2, n - 2, dest, source[1] );
  1421. } /* DUnpack */
  1422. SHAR_EOF
  1423. cat << \SHAR_EOF > stdstuff.c
  1424. /*
  1425.  *  FILE: stdstuff.c
  1426.  *  Support routines for creating and dealing with standard libraries
  1427.  *  and devices.
  1428.  *
  1429.  *  Public Domain, but keep my name in it as the original author.
  1430.  *  30-Sep-88    Jan Sven Trabandt   added to gimme.lib
  1431.  *  31-Oct-88    Jan Sven Trabandt   added new options
  1432.  *                    made getRidOfStdStuff more controllable
  1433.  */
  1434.  
  1435.  
  1436. #define I_AM_STDSTUFF
  1437. #include "gimmelib/gimmefuncs.h"
  1438. #include "gimmelib/stdstuff.h"
  1439.  
  1440. #ifdef AZTEC_C
  1441. extern int Enable_Abort;
  1442. #endif AZTEC_C
  1443.  
  1444. struct IntuitionBase    *IntuitionBase = NULL;
  1445. struct GfxBase        *GfxBase = NULL;
  1446. struct DiskfontBase    *DiskfontBase = NULL;
  1447. struct Device        *TimerBase = NULL;
  1448.  
  1449. struct MsgPort        *gimTimerPort = NULL;
  1450. struct timerequest  *gimMasterTR = NULL;
  1451. struct timerequest  *gimSlaveTR = NULL;
  1452.  
  1453. struct MsgPort        *gimMainPort = NULL;
  1454. SHORT            gimSubTasks = 0;
  1455.  
  1456. void            *gimChainMem = NULL;
  1457.  
  1458.  
  1459. ULONG gimmeStdStuff( myflags, rev )
  1460.     ULONG   myflags;
  1461.     SHORT   rev;
  1462. {
  1463.     if( myflags & GSS_DISABLEABORT ) {
  1464. #ifdef AZTEC_C
  1465.     Enable_Abort = 0;
  1466. #endif
  1467.     }
  1468.     if( myflags & GSS_INTUITION ) {
  1469.     if( !(IntuitionBase = (struct IntuitionBase *)
  1470.                 OpenLibrary("intuition.library", (long) rev)) ) {
  1471.         return( GSS_INTUITION );
  1472.     }
  1473.     }
  1474.     if( myflags & GSS_GFX ) {
  1475.     if( !(GfxBase = (struct GfxBase *)
  1476.                 OpenLibrary("graphics.library", (long) rev)) ) {
  1477.         return( GSS_GFX );
  1478.     }
  1479.     }
  1480.     if( myflags & GSS_CLOSEWBENCH ) {
  1481.     if( CloseWorkBench() ) {
  1482.         return( GSS_CLOSEWBENCH );
  1483.     }
  1484.     }
  1485.     if( myflags & GSS_DISKFONT ) {
  1486.     if( !(DiskfontBase = (struct DiskfontBase *)
  1487.                 OpenLibrary("diskfont.library", (long) rev)) ) {
  1488.         return( GSS_DISKFONT );
  1489.     }
  1490.     }
  1491.     if( myflags & GSS_TIMER ) {
  1492.     if( !(gimMasterTR = accessTimer(UNIT_MICROHZ, &gimTimerPort)) ) {
  1493.         return( GSS_TIMER );
  1494.     }
  1495.     if( !(gimSlaveTR = gimmeTimeRequest(gimMasterTR)) ) {
  1496.         return( GSS_TIMER );
  1497.     }
  1498.     }
  1499.     if( myflags & GSS_SUBTASK ) {
  1500.     if( initSubTasker(&gimSubTasks, &gimMainPort) ) {
  1501.         return( GSS_SUBTASK );
  1502.     }
  1503.     }
  1504.     return( 0L );
  1505. } /* gimmeStdStuff */
  1506.  
  1507.  
  1508. ULONG getRidOfStdStuff( myflags )
  1509.     ULONG   myflags;
  1510. {
  1511.     if( myflags & GSS_MEMCHAIN ) {
  1512.     if( gimChainMem ) {
  1513.         chainFreeMem( gimChainMem );
  1514.         gimChainMem = NULL;
  1515.     }
  1516.     }
  1517.     if( myflags & GSS_SUBTASK ) {
  1518.     if( gimMainPort ) {
  1519.         handleSpecialSubTaskMsg( &gimSubTasks, &gimMainPort );
  1520.         if( doneSubTasker(&gimSubTasks, &gimMainPort)
  1521.             && !(myflags & GSS_RUTHLESS) ) {
  1522.         return( GSS_SUBTASK );
  1523.         }
  1524.         gimSubTasks = 0;
  1525.         gimMainPort = NULL;
  1526.     }
  1527.     }
  1528.     if( myflags & GSS_TIMER ) {
  1529.     if( gimSlaveTR ) {
  1530.         if( getRidOfTimeRequest(gimSlaveTR) && !(myflags & GSS_RUTHLESS) ) {
  1531.         return( GSS_TIMER );
  1532.         }
  1533.         gimSlaveTR = NULL;
  1534.     }
  1535.     if( gimMasterTR ) {
  1536.         if( releaseTimer(gimMasterTR, NULL) && !(myflags & GSS_RUTHLESS) ) {
  1537.         return( GSS_TIMER );
  1538.         }
  1539.         gimMasterTR = NULL;
  1540.         gimTimerPort = NULL;
  1541.     }
  1542.     }
  1543.     if( myflags & GSS_DISKFONT ) {
  1544.     if( DiskfontBase ) {
  1545.         CloseLibrary( DiskfontBase );
  1546.         DiskfontBase = NULL;
  1547.     }
  1548.     }
  1549.     if( myflags & GSS_OPENWBENCH ) {
  1550.     if( OpenWorkBench() && !(myflags & GSS_RUTHLESS) ) {
  1551.         return( GSS_OPENWBENCH );
  1552.     }
  1553.     }
  1554.     if( myflags & GSS_GFX ) {
  1555.     if( GfxBase ) {
  1556.         CloseLibrary( GfxBase );
  1557.         GfxBase = NULL;
  1558.     }
  1559.     }
  1560.     if( myflags & GSS_INTUITION ) {
  1561.     if( IntuitionBase ) {
  1562.         CloseLibrary( IntuitionBase );
  1563.         IntuitionBase = NULL;
  1564.     }
  1565.     }
  1566.     if( myflags & GSS_ENABLEABORT ) {
  1567. #ifdef AZTEC_C
  1568.     Enable_Abort = 1;
  1569. #endif
  1570.     }
  1571.     return( 0L );
  1572. } /* getRidOfStdStuff */
  1573. SHAR_EOF
  1574. cat << \SHAR_EOF > subtask.c
  1575. /*
  1576.  *  FILE: subtask.c
  1577.  *  Support routines for spawning subtasks (not processes).
  1578.  *  This means the subtask shares the same memory space as its parent task.
  1579.  *
  1580.  *  Note: this "library" is re-entrant, so any task can spawn and keep track
  1581.  *  of its own subtasks independantly of other users of this "library".
  1582.  *
  1583.  *  Public Domain, but keep my name in it as the original author.
  1584.  *  31-Aug-88    Jan Sven Trabandt   first release version
  1585.  *  31-Oct-88    Jan Sven Trabandt   (de)initialize routines moved to subtinit.c
  1586.  *                      so that minimal routines need to be
  1587.  *                      linked in when using stdstuff.c
  1588.  *                    renamed getRidOfSubTask to killSubTask
  1589.  */
  1590.  
  1591.  
  1592. #define I_AM_SUBTASK
  1593. #include "gimmelib/gimmefuncs.h"
  1594.  
  1595.  
  1596. #define MIN_STACK   100L
  1597.  
  1598. #define MIN_COUNT   2
  1599. #define MAX_EXTRA   2
  1600.  
  1601.  
  1602. typedef struct {
  1603.     struct Message msg;
  1604.     ULONG flags;
  1605.     APTR  ptr;
  1606. } DONEMSG;
  1607.  
  1608. #define DONEFLAG    ((1L << 31) + 1857329L)
  1609.  
  1610.  
  1611. /* internal use only!!
  1612.  *
  1613.  * NAME:    a4get, a4put
  1614.  *
  1615.  * SYNOPSIS:    a4value = a4get();
  1616.  *        a4put( a4value );
  1617.  *        LONG a4value;
  1618.  *
  1619.  * DESCRIPTION: Get or put a value into register A4.    MANX specific!!!!
  1620.  *        These two functions are support routines for task creation.
  1621.  *        BECAUSE A4 GETS CLEARED IN THE SUBTASK
  1622.  *        and Manx needs it as a base pointer in small-code model.
  1623.  *        Manx's geta4() won't work if its code is too far away,
  1624.  *        so this ensures a4 is set up.
  1625.  *        I'm not sure if this is only in small code and/or small data.
  1626.  *
  1627.  
  1628. static LONG a4get();
  1629. static VOID a4put();
  1630.  
  1631. #asm
  1632.     cseg
  1633. _a4get:
  1634.     move.l    a4,d0
  1635.     rts
  1636.  
  1637. _a4put:
  1638.     move.l    4(a7),a4
  1639.     rts
  1640. #endasm
  1641.  
  1642.  
  1643. struct Task *gimmeSubTask( countptr, portptr, stack_size, data_size,
  1644.                 myportptr )
  1645.     SHORT        *countptr;
  1646.     struct MsgPort  **portptr;
  1647.     LONG        stack_size, data_size;
  1648.     struct MsgPort  **myportptr;
  1649. {
  1650.     struct Task     *task;
  1651.     DONEMSG        *msg = NULL;
  1652.     struct MemList  *mymemlist;
  1653.     struct myneeds {
  1654.     struct MemList mn_head;         /* 1 MemEntry in the head */
  1655.     struct MemEntry mn_body[MIN_COUNT+MAX_EXTRA-1];
  1656.     } myneeds;
  1657.     UWORD        count = 0;
  1658.  
  1659.     myneeds.mn_head.ml_Node.ln_Type = NT_MEMORY;
  1660.     myneeds.mn_head.ml_Node.ln_Pri  = 0;
  1661.     myneeds.mn_head.ml_Node.ln_Name = NULL;
  1662.  
  1663.     if( data_size > 0L ) {
  1664.     myneeds.mn_head.ml_me[count].me_Reqs = MEMF_PUBLIC | MEMF_CLEAR;
  1665.     myneeds.mn_head.ml_me[count].me_Length = data_size;
  1666.     ++count;
  1667.     }
  1668.     if( myportptr && portptr ) {
  1669.     myneeds.mn_head.ml_me[count].me_Reqs = MEMF_PUBLIC | MEMF_CLEAR;
  1670.     myneeds.mn_head.ml_me[count].me_Length = (LONG) sizeof(DONEMSG);
  1671.     ++count;
  1672.     }
  1673.  
  1674.     /* leave stack and struct Task as last two memory blocks */
  1675.  
  1676.     if( stack_size < MIN_STACK ) {
  1677.     stack_size = MIN_STACK;
  1678.     }
  1679.     myneeds.mn_head.ml_me[count].me_Reqs = MEMF_PUBLIC;
  1680.     myneeds.mn_head.ml_me[count].me_Length = stack_size;
  1681.     ++count;
  1682.     myneeds.mn_head.ml_me[count].me_Reqs = MEMF_PUBLIC | MEMF_CLEAR;
  1683.     myneeds.mn_head.ml_me[count].me_Length = (LONG) sizeof(struct Task);
  1684.     ++count;
  1685.  
  1686.     myneeds.mn_head.ml_NumEntries = count;
  1687.     mymemlist = (struct MemList *) AllocEntry( &myneeds );
  1688.     if( (ULONG)(mymemlist) & (1L<<31) ) {
  1689.     return( NULL );
  1690.     }
  1691.  
  1692.     --count;
  1693.     task = (struct Task *) mymemlist->ml_me[count].me_Addr;
  1694.     NewList( &task->tc_MemEntry );
  1695.     AddTail( &task->tc_MemEntry, mymemlist );
  1696.  
  1697.     --count;
  1698.     task->tc_SPLower = mymemlist->ml_me[count].me_Addr;     /* stack */
  1699.     task->tc_SPUpper = (APTR) (stack_size + (ULONG) task->tc_SPLower);
  1700.     task->tc_SPReg = task->tc_SPUpper;
  1701.     task->tc_Node.ln_Type = NT_TASK;
  1702.  
  1703.     if( myportptr && portptr ) {
  1704.     --count;
  1705.     msg = (DONEMSG *) mymemlist->ml_me[count].me_Addr;
  1706.     msg->msg.mn_Length = mymemlist->ml_me[count].me_Length;
  1707.     msg->msg.mn_Node.ln_Type = NT_MESSAGE;
  1708.     msg->ptr = (APTR) *portptr;     /* save subtask monitoring port */
  1709.     msg->flags = DONEFLAG;
  1710.     } /* endif */
  1711.     pushTaskStack( task, msg );
  1712.  
  1713.     if( data_size > 0L ) {
  1714.     --count;
  1715.     task->tc_UserData = mymemlist->ml_me[count].me_Addr;
  1716.     }
  1717.     pushTaskStack( task, task->tc_UserData );
  1718.     pushTaskStack( task, myportptr );
  1719.     pushTaskStack( task, countptr );
  1720.  
  1721.     return( task );
  1722. } /* gimmeSubTask */
  1723.  
  1724.  
  1725. /* internal use only!!
  1726.  *
  1727.  * pushTaskStack : push a long value onto the subtask's stack
  1728.  * task struct and stack must already be initialized,
  1729.  * task must not have been started yet.
  1730. static pushTaskStack( task, val )
  1731.     struct Task *task;
  1732.     LONG    val;
  1733. {
  1734.     --((LONG *)task->tc_SPReg);
  1735.     *((LONG *)task->tc_SPReg) = val;
  1736. } /* pushTaskStack */
  1737.  
  1738.  
  1739. /* internal use only!!
  1740.  *
  1741.  * popTaskStack : pop a long value off the subtask's stack
  1742.  * task struct and stack must already be initialized,
  1743.  * task must not have been started yet.
  1744. static LONG popTaskStack( task )
  1745.     struct Task *task;
  1746. {
  1747.     return( *((LONG *)task->tc_SPReg)++ );
  1748. } /* popTaskStack */
  1749.  
  1750.  
  1751. VOID undoGimmeSubTask( task )
  1752.     struct Task *task;
  1753. {
  1754.     if( task ) {
  1755.     FreeEntry( task->tc_MemEntry.lh_Head );
  1756.     }
  1757. } /* undoGimmeSubTask */
  1758.  
  1759.  
  1760. VOID killSubTask( countptr, portptr, task )
  1761.     SHORT        *countptr;
  1762.     struct MsgPort  **portptr;
  1763.     struct Task     *task;
  1764. {
  1765.     struct MsgPort  *myport;
  1766.  
  1767.     if( portptr && (myport = *portptr) ) {
  1768.     *portptr = NULL;
  1769.     DeletePort( myport );
  1770.     }
  1771.     /*    It is permissible to do a Forbid() and RemTask(NULL) [kill myself]
  1772.      *    even though the following Permit() statement would not get executed
  1773.      *    since the OS will take care of things just fine.
  1774.     */
  1775.     Forbid();
  1776.     if( countptr ) {
  1777.     --(*countptr);
  1778.     }
  1779.     RemTask( task );
  1780.     Permit();
  1781. } /* killSubTask */
  1782.  
  1783.  
  1784. /*  internal use only!!
  1785.  *
  1786.  *  getRidOfMyself
  1787.  *  what's actually on the stack:
  1788.  *    func    a4    countptr   myport   data    msg  -> see bridgeSubTask
  1789.  *  what getRidOfMyself thinks is there:
  1790.  *    ret-addr dum    [countptr] [myport] [data]  [msg]
  1791.  *  note it doesn't actually know about data, msg and port.
  1792.  *  thus countptr is 1 long past dum, etc.
  1793. static VOID getRidOfMyself( dum )
  1794.     LONG    dum;
  1795. {
  1796.     LONG        *parm;
  1797.     DONEMSG        *msg;
  1798.     struct MsgPort  *mp, *myport;
  1799.  
  1800.     parm = &dum;
  1801.     msg = (DONEMSG *) *(parm + 4);
  1802.     if( msg && (myport = (struct MsgPort *) *(parm + 2)) ) {
  1803.     mp = (struct MsgPort *) msg->ptr;
  1804.     msg->ptr = (APTR) FindTask( NULL );
  1805.     msg->msg.mn_ReplyPort = myport;
  1806.     PutMsg( mp, msg );
  1807.     for( ;; ) {
  1808.         WaitPort( myport );
  1809.         while ( msg = (DONEMSG *) GetMsg(myport) ) {
  1810.         if( msg->msg.mn_Node.ln_Type != NT_REPLYMSG ) {
  1811.             ReplyMsg( msg );
  1812.         } else if( msg->flags == DONEFLAG ) {
  1813.             goto gromyself_done;
  1814.         }
  1815.         } /* while */
  1816.     } /* for */
  1817.     }
  1818. gromyself_done:
  1819.     killSubTask( *(parm + 1), parm + 2, NULL );
  1820. } /* getRidOfMyself */
  1821.  
  1822.  
  1823. /*  internal use only!!
  1824.  *
  1825.  *  bridgeSubTask
  1826.  *  Used as the actual initialPC for the subtask, it gets a message port
  1827.  *  if necessary and calls the real subtask routine.
  1828.  *  Also increments the subtask counter!!!!
  1829.  *  Also changes portptr on the stack to port (ie a pointer to a port, not
  1830.  *  a pointer to a pointer) so things are kosher for getRidOfMyself.
  1831.  *  startSubTask does the set-up so that the new subtask starts executing
  1832.  *  with this routine.
  1833. static VOID bridgeSubTask( func, a4, countptr, myportptr, data, msg )
  1834.     long        (*func)();
  1835.     LONG        a4;
  1836.     SHORT        *countptr;
  1837.     struct MsgPort  **myportptr;
  1838.     APTR        data;
  1839.     DONEMSG        *msg;
  1840. {
  1841.     a4put( a4 );
  1842.     if( countptr ) {
  1843.     Forbid();
  1844.     ++(*countptr);
  1845.     Permit();
  1846.     }
  1847.     if( myportptr ) {
  1848.     *myportptr = CreatePort( NULL, 0L );
  1849.     if( !*myportptr ) {
  1850.         return;
  1851.     }
  1852.     *((struct MsgPort **)&myportptr) = *myportptr;
  1853.     }
  1854.     func( data );
  1855. } /* bridgeSubTask */
  1856.  
  1857.  
  1858. short startSubTask( task, name, pri, initialpc, finalpc )
  1859.     struct Task *task;
  1860.     char    *name;
  1861.     BYTE    pri;
  1862.     void    (*initialpc)(), (*finalpc)();
  1863. {
  1864.     if( !task || !initialpc ) {
  1865.     return( -1 );
  1866.     }
  1867.     task->tc_Node.ln_Name = name;
  1868.     task->tc_Node.ln_Pri  = pri;
  1869.     pushTaskStack( task, a4get() );
  1870.     pushTaskStack( task, initialpc );
  1871.     if( !finalpc ) {
  1872.     (APTR) finalpc = (APTR) getRidOfMyself;
  1873.     }
  1874.     AddTask( task, bridgeSubTask, finalpc );
  1875.     return( 0 );
  1876. } /* startSubTask */
  1877. SHAR_EOF
  1878. cat << \SHAR_EOF > subtinit.c
  1879. /*
  1880.  *  FILE: subtinit.c
  1881.  *  Support routines for spawning subtasks (not processes).
  1882.  *  This means the subtask shares the same memory space as its parent task.
  1883.  *
  1884.  *  Note: this "library" is re-entrant, so any task can spawn and keep track
  1885.  *  of its own subtasks independantly of other users of this "library".
  1886.  *
  1887.  *  Public Domain, but keep my name in it as the original author.
  1888.  *  31-Oct-88    Jan Sven Trabandt   split from subtask.c
  1889.  */
  1890.  
  1891.  
  1892. #define I_AM_SUBTINIT
  1893. #include "gimmelib/gimmefuncs.h"
  1894. #define GIM_BUILTIN
  1895. #include "gimmelib/macros.h"
  1896.  
  1897.  
  1898. short initSubTasker( countptr, portptr )
  1899.     SHORT        *countptr;
  1900.     struct MsgPort  **portptr;
  1901. {
  1902.     if( countptr ) {
  1903.     *countptr = 0;
  1904.     }
  1905.     if( portptr ) {
  1906.     *portptr = CreatePort( NULL, 0L );
  1907.     if( !*portptr ) {
  1908.         return( -1 );
  1909.     }
  1910.     }
  1911.     return( 0 );
  1912. } /* initSubTasker */
  1913.  
  1914.  
  1915. short doneSubTasker( countptr, portptr )
  1916.     SHORT        *countptr;
  1917.     struct MsgPort  **portptr;
  1918. {
  1919.     struct MsgPort  *myport;
  1920.  
  1921.     if( countptr && *countptr ) {
  1922.     return( -1 );
  1923.     }
  1924.     if( portptr && (myport = *portptr) ) {
  1925.     *portptr = NULL;
  1926.     DeletePort( myport );
  1927.     }
  1928.     return( 0 );
  1929. } /* doneSubTasker */
  1930.  
  1931.  
  1932. /****************************************************************/
  1933. /* routines to handle printing messages from subtasks to Output()
  1934.  
  1935. extern struct Message *gimmeMessage();
  1936.  
  1937. struct print_msg {
  1938.     struct Message msg;
  1939.     ULONG flags;
  1940.     UBYTE buf[164];
  1941. };
  1942. typedef struct print_msg PRINTMSG;
  1943.  
  1944. #define PRINTMSG_FLAG    218572L
  1945.  
  1946.  
  1947. short doPrintf( port, replyport, s, p1, p2, p3, p4 )
  1948.     struct MsgPort  *port, *replyport;
  1949.     UBYTE        *s;
  1950.     LONG        p1, p2;
  1951.     double        p3, p4;
  1952. {
  1953.     PRINTMSG    *pmsg;
  1954.  
  1955.     if( !port || !s ) {
  1956.     return( -1 );
  1957.     }
  1958.     pmsg = (PRINTMSG *) gimmeMessage( (ULONG)sizeof(PRINTMSG), replyport );
  1959.     if( !pmsg ) {
  1960.     return( -1 );
  1961.     }
  1962.     pmsg->flags = PRINTMSG_FLAG;
  1963.     sprintf( pmsg->buf, s, p1, p2, p3, p4 );
  1964.     PutMsg( port, pmsg );
  1965.     if( replyport ) {
  1966.     WaitPort( replyport );
  1967.     pmsg = (PRINTMSG *) GetMsg( port );
  1968. /***
  1969.     if( pmsg->msg.mn_Node.ln_Type != NT_REPLYMSG
  1970.          || pmsg->flags != PRINTMSG_FLAG ) {
  1971.     }
  1972. ***/
  1973.     getRidOfMessage( pmsg );
  1974.     } /* endif */
  1975.     return( 0 );
  1976. } /* doPrintf */
  1977.  
  1978.  
  1979. SHORT handleSpecialSubTaskMsg( countptr, portptr )
  1980.     SHORT        *countptr;
  1981.     struct MsgPort  **portptr;
  1982. {
  1983.     PRINTMSG    *msg;
  1984.     SHORT    died = 0;
  1985.  
  1986.     if( !portptr || !*portptr ) {
  1987.     return( died );
  1988.     }
  1989.     while( msg = (PRINTMSG *) GetMsg(*portptr) ) {
  1990.     if( msg->flags == PRINTMSG_FLAG ) {
  1991.         if( Output() ) {
  1992.         Forbid();
  1993.         Write( Output(), msg->buf, (ULONG)strlen(msg->buf) );
  1994.         Permit();
  1995.         }
  1996.         if( !msg->msg.mn_ReplyPort ) {
  1997.         getRidOfMessage( msg );
  1998.         } else {
  1999.         ReplyMsg( msg );
  2000.         }
  2001.     } else {    /* otherwise its a DONEMSG (see subtask.c) */
  2002.         ReplyMsg( msg );
  2003.         ++died;
  2004.     } /* endif */
  2005.     } /* while */
  2006.     return( died );
  2007. } /* handleSpecialSubTaskMsg */
  2008. SHAR_EOF
  2009. cat << \SHAR_EOF > timer.c
  2010. /*
  2011.  *  FILE: timer.c
  2012.  *  Support routines for dealing with the timer device.
  2013.  *
  2014.  *  Public Domain, but keep my name in it as the original author.
  2015.  *  31-Aug-88    Jan Sven Trabandt   first release version
  2016.  *  31-Oct-88    Jan Sven Trabandt   most routines moved to timerstuff.c
  2017.  *                      so that minimal routines need to be
  2018.  *                      linked in when using stdstuff.c
  2019.  */
  2020.  
  2021.  
  2022. #define I_AM_TIMER
  2023. #include "gimmelib/gimmefuncs.h"
  2024.  
  2025. extern struct Device *TimerBase;
  2026.  
  2027.  
  2028. struct timerequest *accessTimer( unit, portptr )
  2029.     ULONG        unit;
  2030.     struct MsgPort  **portptr;
  2031. {
  2032.     struct MsgPort    *timerport = NULL;
  2033.     struct timerequest    *tr;
  2034.  
  2035. #ifdef GIMME_WIMPY
  2036.     if( unit != UNIT_VBLANK && unit != UNIT_MICROHZ ) {
  2037.     return( NULL );
  2038.     }
  2039. #endif
  2040.     if( portptr && *portptr ) {
  2041.     timerport = *portptr;
  2042.     } else {
  2043.     timerport = CreatePort( NULL, 0L );
  2044.     if( portptr ) {
  2045.         *portptr = timerport;
  2046.     }
  2047.     }
  2048.     if( !timerport ) {
  2049.     return( NULL );
  2050.     }
  2051.     tr = CreateExtIO( timerport, (ULONG)sizeof(struct timerequest) );
  2052.     if( !tr ) {
  2053.     DeletePort( timerport );
  2054.     } else {
  2055.     if( OpenDevice(TIMERNAME, unit, tr, 0L) ) {
  2056.         DeleteExtIO( tr, (ULONG)sizeof(struct timerequest) );
  2057.         DeletePort( timerport );
  2058.         return( NULL );
  2059.     }
  2060.     }
  2061.     TimerBase = tr->tr_node.io_Device;
  2062.     tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
  2063.     return( tr );
  2064. } /* accessTimer */
  2065.  
  2066.  
  2067. LONG releaseTimer( tr, saveport )
  2068.     register struct timerequest *tr;
  2069.     struct MsgPort  *saveport;
  2070. {
  2071.     struct MsgPort  *tport;
  2072.     LONG        err;
  2073.  
  2074. #ifdef GIMME_WIMPY
  2075.     if( !tr ) {
  2076.     return( 0L );
  2077.     }
  2078. #endif
  2079.     tport = tr->tr_node.io_Message.mn_ReplyPort;
  2080.     if( tr->tr_node.io_Message.mn_Node.ln_Type == NT_MESSAGE ) {
  2081.     if( err = AbortIO(tr) ) {
  2082.         return( err );
  2083.     }
  2084.     Remove( tr );
  2085.     }
  2086.     CloseDevice( tr );
  2087.     DeleteExtIO( tr, (ULONG)sizeof(struct timerequest) );
  2088.     if( !saveport && tport ) {
  2089.     DeletePort( tport );
  2090.     }
  2091.     return( 0L );
  2092. } /* releaseTimer */
  2093.  
  2094.  
  2095. struct timerequest *gimmeTimeRequest( trmaster )
  2096.     struct timerequest    *trmaster;
  2097. {
  2098.     register struct timerequest *tr;
  2099.  
  2100. #ifdef GIMME_WIMPY
  2101.     if( !trmaster ) {
  2102.     return( NULL );
  2103.     }
  2104. #endif
  2105.     tr = CreateExtIO( trmaster->tr_node.io_Message.mn_ReplyPort,
  2106.             (ULONG)sizeof(struct timerequest) );
  2107.     if( tr ) {
  2108.     tr->tr_node.io_Device = trmaster->tr_node.io_Device;
  2109.     tr->tr_node.io_Unit   = trmaster->tr_node.io_Unit;
  2110.     tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
  2111.     }
  2112.     return( tr );
  2113. } /* gimmeTimeRequest */
  2114.  
  2115.  
  2116. LONG getRidOfTimeRequest( tr )
  2117.     register struct timerequest *tr;
  2118. {
  2119.     LONG    err;
  2120.  
  2121. #ifdef GIMME_WIMPY
  2122.     if( !tr ) {
  2123.     return( 0L );
  2124.     }
  2125. #endif
  2126.     Forbid();
  2127.     tr->tr_node.io_Message.mn_ReplyPort = NULL;
  2128.     if( tr->tr_node.io_Message.mn_Node.ln_Type == NT_MESSAGE ) {
  2129.     if( err = AbortIO(tr) ) {
  2130.         Permit();
  2131.         return( err );
  2132.     }
  2133.     Remove( tr );
  2134.     tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
  2135.     }
  2136.     Permit();
  2137.     DeleteExtIO( tr, (ULONG)sizeof(struct timerequest) );
  2138.     return( 0L );
  2139. } /* getRidOfTimeRequest */
  2140. SHAR_EOF
  2141. cat << \SHAR_EOF > timerstuff.c
  2142. /*
  2143.  *  FILE: timerstuff.c
  2144.  *  Support routines for dealing with timerequests and additional timer support.
  2145.  *
  2146.  *  Public Domain, but keep my name in it as the original author.
  2147.  *  31-Oct-88    Jan Sven Trabandt   split from timer.c
  2148.  */
  2149.  
  2150.  
  2151. #define I_AM_TIMERSTUFF
  2152. #include "gimmelib/gimmefuncs.h"
  2153.  
  2154. extern struct Device *TimerBase;
  2155.  
  2156.  
  2157. LONG timeDelay( secs, micros, unit, mytr )
  2158.     ULONG        secs, micros;
  2159.     ULONG        unit;
  2160.     struct timerequest    *mytr;
  2161. {
  2162.     register struct timerequest *tr;
  2163.     LONG    err;
  2164.  
  2165.     if( !secs && !micros ) {
  2166.     return( 0L );           /* so we don't crash, return right away */
  2167.     }
  2168.     if( mytr ) {
  2169.     tr = mytr;
  2170.     } else {
  2171. #ifdef GIMME_WIMPY
  2172.     if( unit != UNIT_VBLANK && unit != UNIT_MICROHZ ) {
  2173.         return( -1L );
  2174.     }
  2175. #endif
  2176.     if( !secs ) {
  2177.         unit = UNIT_MICROHZ;        /* force more efficient method */
  2178.     }
  2179.     if( !(tr = accessTimer(unit, NULL)) ) {
  2180.         return( -1L );
  2181.     }
  2182.     }
  2183.     tr->tr_node.io_Command = TR_ADDREQUEST;
  2184.     tr->tr_time.tv_secs = secs;
  2185.     tr->tr_time.tv_micro = micros;
  2186.     err = DoIO( tr );
  2187.     tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
  2188.     if( !mytr ) {
  2189.     releaseTimer( tr, NULL );
  2190.     }
  2191.     return( err );
  2192. } /* timeDelay */
  2193.  
  2194.  
  2195. struct timerequest *timeDelayAsync( secs, micros, unit, tr )
  2196.     ULONG   secs, micros;
  2197.     ULONG   unit;
  2198.     register struct timerequest *tr;
  2199. {
  2200.     if( !tr ) {
  2201. #ifdef GIMME_WIMPY
  2202.     if( unit != UNIT_VBLANK && unit != UNIT_MICROHZ ) {
  2203.         return( NULL );
  2204.     }
  2205. #endif
  2206.     if( !secs ) {
  2207.         unit = UNIT_MICROHZ;        /* force more efficient method */
  2208.     }
  2209.     if( !(tr = accessTimer(unit, NULL)) ) {
  2210.         return( NULL );
  2211.     }
  2212.     }
  2213.     if( !secs && !micros ) {
  2214.     micros = 1L;            /* so we don't crash on zero-delay */
  2215.     }
  2216.     tr->tr_node.io_Command = TR_ADDREQUEST;
  2217.     tr->tr_time.tv_secs = secs;
  2218.     tr->tr_time.tv_micro = micros;
  2219.     SendIO( tr );
  2220.     return( tr );
  2221. } /* timeDelayAsync */
  2222.  
  2223.  
  2224. LONG waitTimer( tr )
  2225.     struct timerequest    *tr;
  2226. {
  2227.     LONG    err = 0L;
  2228.  
  2229. #ifdef GIMME_WIMPY
  2230.     if( !tr ) {
  2231.     return( err );
  2232.     }
  2233. #endif
  2234.     err = WaitIO( tr );
  2235.     tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
  2236.     return( err );
  2237. } /* waitTimer */
  2238.  
  2239.  
  2240. LONG killTimeDelay( tr )
  2241.     register struct timerequest *tr;
  2242. {
  2243.     LONG    err;
  2244.  
  2245. #ifdef GIMME_WIMPY
  2246.     if( !tr ) {
  2247.     return( 0L );
  2248.     }
  2249. #endif
  2250.     Forbid();
  2251.     if( tr->tr_node.io_Message.mn_Node.ln_Type == NT_MESSAGE ) {
  2252.     if( err = AbortIO(tr) ) {
  2253.         Permit();
  2254.         return( err );
  2255.     }
  2256.     Remove( tr );
  2257.     tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
  2258.     }
  2259.     Permit();
  2260.     return( 0L );
  2261. } /* killTimeDelay */
  2262.  
  2263.  
  2264. short getSysTime( secs, micros, mytr )
  2265.     ULONG        *secs, *micros;
  2266.     struct timerequest    *mytr;
  2267. {
  2268.     register struct timerequest *tr;
  2269.  
  2270.     if( mytr ) {
  2271.     tr = mytr;
  2272.     } else {
  2273.     if( !(tr = accessTimer(UNIT_MICROHZ, NULL)) ) {
  2274.         return( -1 );
  2275.     }
  2276.     }
  2277.     tr->tr_node.io_Command = TR_GETSYSTIME;
  2278.     DoIO( tr );
  2279.     tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
  2280.     if( secs ) {
  2281.     *secs = tr->tr_time.tv_secs;
  2282.     }
  2283.     if( micros ) {
  2284.     *micros = tr->tr_time.tv_micro;
  2285.     }
  2286.     if( !mytr ) {
  2287.     releaseTimer( tr, NULL );
  2288.     }
  2289.     return( 0 );
  2290. } /* getSysTime */
  2291.  
  2292.  
  2293. short setSysTime( secs, micros, mytr )
  2294.     ULONG        secs, micros;
  2295.     struct timerequest    *mytr;
  2296. {
  2297.     register struct timerequest *tr;
  2298.  
  2299.     if( mytr ) {
  2300.     tr = mytr;
  2301.     } else {
  2302.     if( !(tr = accessTimer(UNIT_MICROHZ, NULL)) ) {
  2303.         return( -1 );
  2304.     }
  2305.     }
  2306.     tr->tr_node.io_Command = TR_SETSYSTIME;
  2307.     tr->tr_time.tv_secs = secs;
  2308.     tr->tr_time.tv_micro = micros;
  2309.     DoIO( tr );
  2310.     tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
  2311.     if( !mytr ) {
  2312.     releaseTimer( tr, NULL );
  2313.     }
  2314.     return( 0 );
  2315. } /* setSysTime */
  2316. SHAR_EOF
  2317. cat << \SHAR_EOF > window.c
  2318. /*
  2319.  *  FILE: window.c
  2320.  *  Support routines for dynamic (de)allocation of (new)windows.
  2321.  *
  2322.  *  Public Domain, but keep my name in it as the original author.
  2323.  *  31-Aug-88    Jan Sven Trabandt   first release version
  2324.  */
  2325.  
  2326.  
  2327. #define I_AM_WINDOW
  2328. #include "gimmelib/gimmefuncs.h"
  2329. #include "gimmelib/window.h"
  2330. #include <graphics/gfxbase.h>
  2331.  
  2332. extern struct GfxBase *GfxBase;
  2333.  
  2334.  
  2335. struct NewWindow *gimmeNewWindow( title, screen, leftedge, topedge,
  2336.                     IDCMPflags, flags )
  2337.     UBYTE        *title;
  2338.     struct Screen   *screen;
  2339.     SHORT        leftedge, topedge;
  2340.     ULONG        IDCMPflags, flags;
  2341. {
  2342.     register struct NewWindow    *nw;
  2343.  
  2344.     nw = (struct NewWindow *) AllocMem( (ULONG)sizeof(struct NewWindow),
  2345.                     MEMF_PUBLIC | MEMF_CLEAR );
  2346.     if( !nw ) {
  2347.     return( NULL );
  2348.     }
  2349.     nw->DetailPen = GNW_DETAIL_PEN;
  2350.     nw->BlockPen  = GNW_BLOCK_PEN;
  2351.     nw->IDCMPFlags= IDCMPflags;
  2352.     nw->Flags      = flags;
  2353.     nw->Title      = title;
  2354.     nw->MinWidth  = GNW_MIN_WIDTH;
  2355.     nw->MinHeight = GNW_MIN_HEIGHT;
  2356.     nw->LeftEdge  = leftedge;
  2357.     nw->TopEdge   = topedge;
  2358.     if( screen ) {
  2359.     nw->Type = CUSTOMSCREEN;
  2360.     nw->Screen = screen;
  2361.     nw->MaxWidth  = screen->Width;
  2362.     nw->MaxHeight = screen->Height;
  2363.     } else {
  2364.     nw->Type = WBENCHSCREEN;
  2365.     nw->MaxWidth  = GfxBase->NormalDisplayColumns;
  2366.     nw->MaxHeight = GfxBase->NormalDisplayRows;
  2367.     }
  2368.     nw->Width  = nw->MaxWidth - nw->LeftEdge;
  2369.     nw->Height = nw->MaxHeight - nw->TopEdge;
  2370.     return( nw );
  2371. } /* gimmeNewWindow */
  2372.  
  2373.  
  2374. short getRidOfNewWindow( nw )
  2375.     struct NewWindow    *nw;
  2376. {
  2377. #ifdef GIMME_WIMPY
  2378.     if( !nw ) {
  2379.     return( -1 );
  2380.     }
  2381. #endif
  2382.     FreeMem( nw, (ULONG)sizeof(struct NewWindow) );
  2383.     return( 0 );
  2384. } /* getRidOfNewWindow */
  2385.  
  2386.  
  2387. struct Window *gimmeWindow( nw, depth, width, height )
  2388.     struct NewWindow    *nw;
  2389.     SHORT   depth, width, height;
  2390. {
  2391.     struct Window    *window;
  2392.     struct NewWindow    *mynw;
  2393.  
  2394.     if( !(mynw = nw) ) {
  2395.     nw = gimmeNewWindow( NULL, NULL, 0, 1, IDCMP_DEFAULT, FLAGS_DEFAULT );
  2396.     }
  2397.     for( ;; ) {         /* dummy loop with break at end */
  2398.     if( nw ) {
  2399.         if( nw->Flags & SUPER_BITMAP ) {
  2400.         if( !(nw->BitMap = gimmeBitMap(depth, width, height)) ) {
  2401.             break;
  2402.         }
  2403.         }
  2404.         window = OpenWindow( nw );
  2405.         if( !window ) {
  2406.         if( nw->Flags & SUPER_BITMAP ) {
  2407.             getRidOfBitMap( nw->BitMap );
  2408.         }
  2409.         } else {
  2410.         window->UserData = (BYTE *) nw->BitMap;
  2411.         }
  2412.     }
  2413.     break;
  2414.     } /* for */
  2415.     if( !mynw && nw ) {
  2416.     getRidOfNewWindow( nw );
  2417.     }
  2418.     return( window );
  2419. } /* gimmeWindow */
  2420.  
  2421.  
  2422. short getRidOfWindow( window )
  2423.     struct Window   *window;
  2424. {
  2425.     struct BitMap    *bm = NULL;
  2426.     struct IntuiMessage *imsg;
  2427.  
  2428. #ifdef GIMME_WIMPY
  2429.     if( !window ) {
  2430.     return( -1 );
  2431.     }
  2432. #endif
  2433.     if( window->Flags & SUPER_BITMAP ) {
  2434.     bm = (struct BitMap *) window->UserData;
  2435.     }
  2436.     if( window->MenuStrip ) {
  2437.     ClearMenuStrip( window );
  2438.     }
  2439.     while( imsg = (struct IntuiMessage *) GetMsg(window->UserPort) ) {
  2440.     ReplyMsg( imsg );
  2441.     } /* while */
  2442.     CloseWindow( window );
  2443.     if( bm ) {
  2444.     getRidOfBitMap( bm );
  2445.     }
  2446. } /* getRidOfWindow */
  2447. SHAR_EOF
  2448. #    End of shell archive
  2449. exit 0
  2450. -- 
  2451. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  2452. Have five nice days.
  2453.